package com.piesat.quake.business.station.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.piesat.common.utils.SecurityUtils;
import com.piesat.quake.business.device.bis.DeviceCache;
import com.piesat.quake.business.station.mapper.RegionMapper;
import com.piesat.quake.business.station.model.Region;
import com.piesat.quake.business.station.model.StationInfo;
import com.piesat.quake.business.station.service.RegionService;
import com.piesat.quake.business.station.service.StationInfoService;
import com.piesat.security.service.dto.JwtUserDto;
import com.piesat.security.service.dto.UserDto;

import org.apache.commons.io.FileUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import lombok.RequiredArgsConstructor;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author ${author}
 * @since 2022-12-07
 */
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class RegionServiceImpl extends ServiceImpl<RegionMapper, Region> implements RegionService {

    private final StationInfoService stationInfoService;
    private final DeviceCache deviceCache;
    private static final String NATIONWIDE_CODE = "000000";

//    @PostConstruct
    void init(){
        try {
            String s = FileUtils.readFileToString(new File("F:\\project\\quake-server\\src\\main\\resources\\code.json"), StandardCharsets.UTF_8.name());
            JSONArray objects = JSONArray.parseArray(s);
            List<Region> regions=new LinkedList<>();
            for (Object object : objects) {
                JSONObject jsonObject = (JSONObject) object;
                String label = jsonObject.getString("label");
                String value = jsonObject.getString("value");
                Region region = new Region();
                region.setCode(value);
                region.setName(label);
                region.setParent(NATIONWIDE_CODE);
                regions.add(region);
                JSONArray children = jsonObject.getJSONArray("children");
                for (Object child : children) {
                    JSONObject json = (JSONObject) child;
                    String name = json.getString("label");
                    String code = json.getString("value");
                    Region region1 = new Region();
                    region1.setCode(code);
                    region1.setName(name);
                    region1.setParent(value);
                    regions.add(region1);
                }
            }

            saveBatch(regions);

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void addRegion(Region region) {
        Region oldRegion = this.getById(region.getCode());
        assert oldRegion != null : "区划code已经存在";
        this.save(region);
    }

    @Override
    @CacheEvict(cacheNames = "region", key = "#regionCode")
    public void removeRegion(String regionCode) {
        assert this.getById(regionCode) == null : "区划code不存在";
        //移除所有和该区划有关联的站点关联
        stationInfoService.lambdaUpdate().eq(StationInfo::getRegionCode, regionCode)
                .set(StationInfo::getRegionCode, null).update();
        this.removeById(regionCode);
    }

    @Override
    @CachePut(cacheNames = "region", key = "#region.code")
    public void updateRegion(Region region) {
        assert this.getById(region.getCode()) == null : "区划code不存在";
        this.updateById(region);
    }

    @Override
    public List<Region> findRegionList() {
        return this.list();
    }

    public List<Region> getParentList(){
        QueryWrapper<Region> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent",NATIONWIDE_CODE)
        .orderByAsc("code");
        return baseMapper.selectList(queryWrapper);
    }

    @Override
    public List<Region> buildTree() {
        JwtUserDto userDetails = (JwtUserDto) SecurityUtils.getCurrentUser();
        UserDto user = userDetails.getUser();
        List<Region> list = baseMapper.getRegionList(user.getId());
        List<Region> parentList = getParentList();
        Map<String,List<Region>> regionMap=new HashMap<>();
        for (Region region : list) {
            String parent = region.getParent();
            List<Region> regions = regionMap.computeIfAbsent(parent, k -> new LinkedList<>());
            regions.add(region);
            region.setStationInfoList(stationInfoService.findStationInfoList(region.getCode()));
//            region.setStationInfoList(deviceCache.getByRegionCode(region.getCode()));
        }
        List<Region> regions = new ArrayList<>(regionMap.size());
        for (Region region : parentList) {
            if (regionMap.containsKey(region.getCode())){
                List<Region> regions1 = regionMap.get(region.getCode());
                region.setRegions(regions1);
                regions.add(region);
                regionMap.remove(region.getCode());
            }
        }
        return regions;
    }

    @Override
    @Cacheable(cacheNames = "region", key = "#code")
    public Region findByCode(String code) {
        return this.getById(code);
    }
}
